import json
import logging
import os
import re
import subprocess
from difflib import SequenceMatcher
from typing import List


def system_call(command):
    result = subprocess.run(command, shell=True, capture_output=True, text=True)
    if result.returncode != 0:
        pass
    return result.returncode, result.stdout, result.stderr

def load_jsonl(s: str):
    output = []
    for line in s.splitlines():
        output.append(json.loads(line))
    return output

def save_jsonl(path, jsons):
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, 'a', encoding='utf-8') as fp:
        for json_data in jsons:
            json_str = json.dumps(json_data, ensure_ascii=False)
            fp.write(json_str + '\n')

def read_file(file):
    with open(file, 'r', encoding='utf-8') as fp:
        content = fp.read()
    return content

def write_file(file, content):
    dirname = os.path.dirname(file)
    os.makedirs(dirname, exist_ok=True)
    with open(file, 'w', encoding='utf-8') as fp:
        fp.write(content)

def rename_file_to_temp(file_path):
    temp_file = str(file_path) + '.tmp'
    if os.path.exists(temp_file):
        os.remove(temp_file)
    os.renames(file_path, temp_file)
    return temp_file

def rename_file_from_temp(temp_file):
    temp_file = str(temp_file)
    file_path = temp_file[:-4]
    if os.path.exists(file_path):
        os.remove(file_path)
    os.renames(temp_file, file_path)
    return file_path

def similar_ratio(str1, str2):
    # 返回0到1之间的相似度
    return SequenceMatcher(None, str1, str2).ratio()

def find_most_similar(target, candidates):
    """找出最相似的字符串"""
    similarities = [(c, SequenceMatcher(None, target, c).ratio())
                    for c in candidates]
    return max(similarities, key=lambda x: x[1])

def find_most_similar_uncased(query: str, word_list: List[str]) -> tuple[str, float]:
    """
    找出与查询词最相似的单词

    参数:
        query: 查询词
        word_list: 候选词列表

    返回:
        最相似的单词和相似度分数的元组
    """
    query = query.lower()  # 转换查询词为小写
    max_ratio = 0
    most_similar = word_list[0]

    for word in word_list:
        # 转换为小写进行比较
        ratio = SequenceMatcher(None, query, word.lower()).ratio()
        if ratio > max_ratio:
            max_ratio = ratio
            most_similar = word

    return most_similar, max_ratio

def get_logger(name, log_path=None):
    """
    获取或创建一个只输出到文件的logger

    Args:
        name (str): logger的名称
        log_path (str, optional): 日志文件路径，如果logger不存在时必须提供

    Returns:
        logging.Logger: 配置好的logger对象

    Raises:
        ValueError: 当logger不存在且未提供log_path时抛出
    """
    # 检查logger是否已存在
    logger = logging.getLogger(name)

    # 如果logger已经有处理器，说明已经配置过，直接返回
    if logger.handlers:
        return logger

    # 如果logger不存在且未提供log_path，抛出异常
    if not log_path:
        raise ValueError("Logger不存在，必须提供log_path来创建新的logger")

    # 确保日志目录存在
    os.makedirs(os.path.dirname(log_path), exist_ok=True)

    # 配置日志格式
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )

    # 创建文件处理器
    file_handler = logging.FileHandler(log_path, encoding='utf-8')
    file_handler.setFormatter(formatter)

    # 设置日志级别
    logger.setLevel(logging.INFO)

    # 添加处理器
    logger.addHandler(file_handler)

    return logger

def split_by_non_var_chars(text):
    # 匹配一个或多个非变量命名字符(不是字母数字下划线的字符)
    return [word for word in re.split(r'[^a-zA-Z0-9_]+', text) if word]